/**
 * Created by brss on 2018/3/24.
 */
public class Visbility {

    /**
     * CPU和内存直接，其实还有一层缓存在中间连接，当从缓存中读到变量值的时候，CPU就不会从内存中读了。
     * （而使用volatile后，保证每次读取都是从内存中读取的，也就是说一个线程修改了一个东西后，另一个线程立刻就能读取到最新的内容了。）
     * volatile保证变量的修改让所有线程可见
     * volatile阻止指令排序
     *
     * volatile特性一：内存可见性，即线程A对volatile变量的修改，其他线程获取的volatile变量都是最新的。
     * volatile特性二：可以禁止指令重排序
     *
     * volatile是个古老的关键字，syn优化的比较好，不要可以用它
     *
     * syn 能够解决 可见性 原子性   volatile只能解决可见性
     *
     * 先比较 后修改  CAS compare and set   （线程1比较后，修改，线程2在比较时，需要考虑拿到的数据是否是刚才修改过的新数据）
     *
     * 线程封闭 ： 把类声明为 final
     * 栈封闭 比如说方法内部声明修改 不会溢出
     * ThreadLocal 线程绑定
     */
    private volatile static boolean bChanged;

    private static ThreadLocal<LocalTest> threadLocal = new ThreadLocal<LocalTest>();

    /*public static void main(String[] args) throws InterruptedException {
        new Thread(){
            public void run(){
                for (;;){
                    if (bChanged==true){
                        System.out.println("!=");
                        System.exit(0);
                    }
                }
            }
        }.start();
        Thread.sleep(10);


        new Thread(){
            public void run(){
                bChanged = true;
            }
        }.start();
    }*/


    public static void main(String[] args) {
        LocalTest local = new LocalTest();
        new Thread(){
            public void run(){
                for(;;){
                    threadLocal.set(local);
                    LocalTest l = threadLocal.get();
                    l.setNum(20);
                    System.out.println(Thread.currentThread().getName()+"-----"+threadLocal.get().getNum());
                    Thread.yield();
                }
            }
        }.start();




        new Thread(){
            public void run(){
                for(;;){
                    threadLocal.set(local);
                    LocalTest l = threadLocal.get();
                    l.setNum(30);
                    System.out.println(Thread.currentThread().getName()+"-----"+threadLocal.get().getNum());
                    Thread.yield();
                }
            }
        }.start();











    }



}
